{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "cutting-premiere",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "august-object",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(800000, 47)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = pd.read_csv(r'./data/train.csv')\n",
    "data.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "trying-jewel",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>grade</th>\n",
       "      <th>term</th>\n",
       "      <th>openAcc</th>\n",
       "      <th>label</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>E</td>\n",
       "      <td>5</td>\n",
       "      <td>7</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>D</td>\n",
       "      <td>5</td>\n",
       "      <td>13</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>D</td>\n",
       "      <td>5</td>\n",
       "      <td>11</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>A</td>\n",
       "      <td>3</td>\n",
       "      <td>9</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>C</td>\n",
       "      <td>3</td>\n",
       "      <td>12</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  grade  term  openAcc  label\n",
       "0     E     5        7      1\n",
       "1     D     5       13      0\n",
       "2     D     5       11      0\n",
       "3     A     3        9      0\n",
       "4     C     3       12      0"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data_20k = data[['grade','term','openAcc','isDefault']].head(20000).copy()\n",
    "\n",
    "data_20k['openAcc'] = data_20k['openAcc'].astype(int)\n",
    "data_20k.rename(columns={'isDefault':'label'}, inplace=True)\n",
    "data_20k.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "square-rogers",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "根节点信息熵： 0.7209269670764653\n",
      "当前特征：grade\n",
      "0.6695886834231076\n",
      "当前特征：term\n",
      "0.701461940742094\n",
      "当前特征：openAcc\n",
      "0.7185794170486539\n"
     ]
    }
   ],
   "source": [
    "def entropy(data, feature=None, label='label'):\n",
    "    total = data.shape[0]\n",
    "    if 'index' not in data.columns.tolist():\n",
    "        data.reset_index(inplace=True)\n",
    "    if feature is None:   \n",
    "        dist = data[label].value_counts() / total\n",
    "        h = - np.sum(dist * np.log2(dist))\n",
    "        return h\n",
    "    else:\n",
    "        feature_cnt_field = f\"{feature}_cnt\"\n",
    "        feature_share = f\"{feature}_share\"\n",
    "        value_share = \"value_share\"\n",
    "        index = \"index\"\n",
    "        h_value = \"h_value\"\n",
    "        dist = data[feature].value_counts()\n",
    "        dist = dist.reset_index().rename(columns={\"index\":feature, feature:feature_cnt_field})\n",
    "        dist[feature_share] = dist[feature_cnt_field] / total\n",
    "        h_a = data.groupby([feature, label])[index].count().reset_index()\n",
    "        h_a = pd.merge(h_a, dist,how='left',on=feature)\n",
    "        h_a[value_share] = h_a[index] / h_a[feature_cnt_field]\n",
    "        h_a[h_value] = np.log2(h_a[value_share])\n",
    "        g = h_a.groupby(feature).apply(lambda df:df[feature_share].values[0]*(df[value_share]*df[h_value]).sum())\n",
    "        return -np.sum(g)\n",
    "\n",
    "print(\"根节点信息熵：\",entropy(data_20k))\n",
    "for feature in ['grade','term','openAcc']:\n",
    "    print(f\"当前特征：{feature}\")  \n",
    "    h = entropy(data_20k, feature=feature)  \n",
    "    print(h)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "extended-separation",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
